"""
文件处理服务
"""

import aiofiles
import logging
from pathlib import Path
from typing import List, Optional
from fastapi import UploadFile, HTTPException

from ..core.config import settings

logger = logging.getLogger(__name__)

class FileService:
    """文件处理服务"""
    
    @staticmethod
    def validate_file(file: UploadFile) -> None:
        """验证上传文件"""
        # 检查文件扩展名
        if not file.filename:
            raise HTTPException(status_code=400, detail="文件名不能为空")
        
        file_ext = Path(file.filename).suffix.lower()
        if file_ext not in settings.ALLOWED_EXTENSIONS:
            raise HTTPException(
                status_code=400, 
                detail=f"不支持的文件格式: {file_ext}。支持的格式: {', '.join(settings.ALLOWED_EXTENSIONS)}"
            )
        
        # 检查文件大小（这里只能检查已知的大小，实际大小在保存时检查）
        if hasattr(file, 'size') and file.size and file.size > settings.MAX_FILE_SIZE:
            raise HTTPException(
                status_code=413, 
                detail=f"文件过大。最大允许: {settings.MAX_FILE_SIZE / (1024*1024):.0f}MB"
            )
    
    @staticmethod
    async def save_upload_file(file: UploadFile) -> Path:
        """保存上传文件"""
        FileService.validate_file(file)
        
        # 确保上传目录存在
        settings.UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
        
        # 生成唯一文件名
        import uuid
        file_ext = Path(file.filename).suffix.lower()
        unique_filename = f"{uuid.uuid4()}{file_ext}"
        file_path = settings.UPLOAD_DIR / unique_filename
        
        # 保存文件并检查大小
        total_size = 0
        async with aiofiles.open(file_path, 'wb') as f:
            while True:
                chunk = await file.read(8192)  # 8KB chunks
                if not chunk:
                    break
                
                total_size += len(chunk)
                if total_size > settings.MAX_FILE_SIZE:
                    # 删除部分上传的文件
                    try:
                        file_path.unlink()
                    except:
                        pass
                    raise HTTPException(
                        status_code=413,
                        detail=f"文件过大。最大允许: {settings.MAX_FILE_SIZE / (1024*1024):.0f}MB"
                    )
                
                await f.write(chunk)
        
        logger.info(f"文件保存成功: {file.filename} -> {file_path}")
        return file_path
    
    @staticmethod
    def cleanup_upload_file(file_path: Path) -> None:
        """清理上传文件"""
        try:
            if file_path.exists():
                file_path.unlink()
                logger.info(f"清理上传文件: {file_path}")
        except Exception as e:
            logger.warning(f"清理上传文件失败 {file_path}: {str(e)}")
    
    @staticmethod
    def get_file_info(file_path: Path) -> dict:
        """获取文件基本信息"""
        if not file_path.exists():
            raise FileNotFoundError(f"文件不存在: {file_path}")
        
        stat = file_path.stat()
        return {
            "name": file_path.name,
            "size": stat.st_size,
            "size_mb": round(stat.st_size / (1024 * 1024), 2),
            "extension": file_path.suffix.lower(),
            "created_at": stat.st_ctime,
            "modified_at": stat.st_mtime
        }
    
    @staticmethod
    def is_large_file(file_path: Path) -> bool:
        """检查是否为大文件"""
        return file_path.stat().st_size > settings.LARGE_FILE_THRESHOLD